#!/usr/bin/env bash
__Author__="liy"

source ./functions.sh
export CERT_DIR="${ROOT_DIR}/${1:-"kubernetes"}"
export ETCD_CERT_DIR="${ROOT_DIR}/${2:-"etcd"}"

which kubectl &>/dev/null
if [ $? -ne 0 ];then
    echo -e "\033[31mkubectl command not found!\033[0m"
    exit 1
fi

function init_env(){
    mkdir -pv $CERT_DIR
}


function create_ca(){
    openssl genrsa -out $CERT_DIR/ca.key 2048
    openssl req -config openssl.conf \
    -new -x509 -days 36500 -sha256 \
    -key $CERT_DIR/ca.key -out $CERT_DIR/ca.crt \
    -subj "/CN=kubernetes"

    touch $CERT_DIR/{index,index.txt}
    echo "1000" > $CERT_DIR/serial
    echo "unique_subject = no" > $CERT_DIR/index.txt.attr

    CA_CERT="$CERT_DIR/ca.crt"
    CA_KEY="$CERT_DIR/ca.key"
}


function bootstrap_token(){
    #export BOOTSTRAP_TOKEN="$(head -c 32 /dev/urandom |md5sum |head -c 32)"
    export BOOTSTRAP_TOKEN="$(head -c 6 /dev/urandom | md5sum |head -c 6).$(head -c 16 /dev/urandom | md5sum | head -c 16)"
    echo "$BOOTSTRAP_TOKEN,kubelet-bootstrap,10001,\"system:bootstrappers\"" > ${CERT_DIR}/token.csv
}

function kubeconfig(){
    # $1 保存的文件名
    # $2 用户名
    # $3 认证文件
    kubectl config --kubeconfig=${CERT_DIR}/$1 set-cluster $CLUSTER_NAME --server=https://"$CLUSTER_NAME-api.$BASE_DOMAIN:6443" --certificate-authority="$CERT_DIR/ca.crt" --embed-certs=true
    kubectl config --kubeconfig=${CERT_DIR}/$1 set-credentials $2 --client-certificate ${CERT_DIR}/$3.crt --client-key ${CERT_DIR}/$3.key --embed-certs=true
    kubectl config --kubeconfig=${CERT_DIR}/$1 set-context "$2@$CLUSTER_NAME" --user=$2 --cluster=$CLUSTER_NAME
    kubectl config --kubeconfig=${CERT_DIR}/$1 use-context "$2@$CLUSTER_NAME"
}


function master(){
    # KubeAPIServer
    openssl_req "${CERT_DIR}" apiserver "/CN=kube-apiserver"
    openssl_sign $CA_CERT $CA_KEY "${CERT_DIR}" apiserver apiserver_cert

    # KubeControllerManager
    openssl_req "${CERT_DIR}" kube-controller-manager "/CN=system:kube-controller-manager"
    openssl_sign $CA_CERT $CA_KEY "${CERT_DIR}" kube-controller-manager master_component_client_cert
    kubeconfig kube-controller-manager.kubeconfig "system:kube-controller-manager"  kube-controller-manager
   
    # KubeScheduler
    openssl_req "${CERT_DIR}" kube-scheduler "/CN=system:kube-scheduler"
    openssl_sign $CA_CERT $CA_KEY "${CERT_DIR}" kube-scheduler master_component_client_cert
    kubeconfig kube-scheduler.kubeconfig "system:kube-scheduler" kube-scheduler

    # KubeletClient
    openssl_req "${CERT_DIR}" apiserver-kubelet-client "/CN=kube-apiserver-kubelet-client/O=system:masters"
    openssl_sign $CA_CERT $CA_KEY "${CERT_DIR}" apiserver-kubelet-client client_cert

    # ServiceAccount
    openssl genrsa -out ${CERT_DIR}/sa.key 2048 
    openssl rsa -in ${CERT_DIR}/sa.key -pubout -outform PEM -out ${CERT_DIR}/sa.pub

    # admin.conf
    kubeconfig admin.kubeconfig "kubernetes-admin" apiserver-kubelet-client
}


function worker(){
    # KubeProxy
    openssl_req ${CERT_DIR} kube-proxy "/CN=system:kube-proxy"
    openssl_sign $CA_CERT $CA_KEY ${CERT_DIR} kube-proxy client_cert
    kubeconfig kube-proxy.kubeconfig "system:kube-proxy" kube-proxy

    # Kubelet Kubeconfig文件
    kubectl config --kubeconfig=${CERT_DIR}/kubelet-bootstrap.kubeconfig set-cluster $CLUSTER_NAME --server=https://"$CLUSTER_NAME-api.$BASE_DOMAIN:6443" --certificate-authority="$CERT_DIR/ca.crt" --embed-certs=true
    kubectl config --kubeconfig=${CERT_DIR}/kubelet-bootstrap.kubeconfig set-credentials kubelet-bootstrap --token="$BOOTSTRAP_TOKEN"
    kubectl config --kubeconfig=${CERT_DIR}/kubelet-bootstrap.kubeconfig set-context bootstrap --user=kubelet-bootstrap --cluster=$CLUSTER_NAME
    kubectl config --kubeconfig=${CERT_DIR}/kubelet-bootstrap.kubeconfig use-context bootstrap
}


function front-proxy(){
    openssl genrsa -out ${CERT_DIR}/front-proxy-ca.key 2048
    openssl req -config openssl.conf \
        -new -x509 -days 36500 -sha256 \
        -key ${CERT_DIR}/front-proxy-ca.key -out ${CERT_DIR}/front-proxy-ca.crt \
        -subj "/CN=front-proxy-ca"

    openssl_req ${CERT_DIR} front-proxy-client "/CN=front-proxy-client"
    openssl_sign ${CERT_DIR}/front-proxy-ca.crt ${CERT_DIR}/front-proxy-ca.key ${CERT_DIR} front-proxy-client client_cert
}


function clone_etcd_certs(){
    if [ -d "$ETCD_CERT_DIR" ];then
        cp $ETCD_CERT_DIR/apiserver-etcd-client.* $CERT_DIR/
    fi
}


function main(){
    init_env
    create_ca
    bootstrap_token
    master
    worker
    front-proxy
    clone_etcd_certs
    clean
}


main

